package com.mjgy.service.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.common.utils.PageUtils;
import com.common.utils.Query;
import com.common.utils.R;
import com.mjgy.controller.MUserController;
import com.mjgy.entity.BroadCastEntity;
import com.mjgy.entity.DeviceCodeEntity;
import com.mjgy.entity.InviteCodeEntity;
import com.mjgy.entity.MUserEntity;
import com.mjgy.entity.MemberEntity;
import com.mjgy.entity.MessageEntity;
import com.mjgy.entity.PhotoViewerEntity;
import com.mjgy.entity.TokenEntity;
import com.mjgy.entity.UserAccessEntity;
import com.mjgy.entity.UserDefriendEntity;
import com.mjgy.entity.UserEvaluateEntity;
import com.mjgy.entity.UserFollowEntity;
import com.mjgy.entity.UserLocationEntity;
import com.mjgy.entity.UserPhotoEntity;
import com.mjgy.entity.UserWithdrawEntity;
import com.mjgy.repository.AlbumUnlockerRepository;
import com.mjgy.repository.BroadCastLikerRepository;
import com.mjgy.repository.BroadCastRepository;
import com.mjgy.repository.BroadCastSignerRepository;
import com.mjgy.repository.CheckWhiteListRepository;
import com.mjgy.repository.ContactWayWhiteListRepository;
import com.mjgy.repository.DeviceCodeRepository;
import com.mjgy.repository.InviteCodeRepository;
import com.mjgy.repository.MUserRepository;
import com.mjgy.repository.MemberRepository;
import com.mjgy.repository.MessageRepository;
import com.mjgy.repository.PayLogRepository;
import com.mjgy.repository.PhotoViewerRepository;
import com.mjgy.repository.RelationshipRepository;
import com.mjgy.repository.TokenRepository;
import com.mjgy.repository.UserLocationRepository;
import com.mjgy.repository.UserReportRepository;
import com.mjgy.repository.UserWithdrawRepository;
import com.mjgy.service.MUserService;
import com.mjgy.utils.JSONUtils;
import com.mjgy.utils.LocationUtils;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* @Description: TODO
* @author LGC
* @date 2018年7月11日
* @version V1.0
*/
@Service(value = "mUserService")
@Transactional
public class MUserServiceImpl implements MUserService {

	@Autowired
	private MUserRepository mUserRepository;
	@Autowired
	private InviteCodeRepository inviteCodeRepository;
	@Autowired
	private UserLocationRepository userLocationRepository;
	@Autowired
	private RelationshipRepository relationshipRepository;
	@Autowired
	private PhotoViewerRepository photoViewerRepository;
	@Autowired
	private TokenRepository tokenRepository;
	@Autowired
	private MemberRepository memberRepository;
	@Autowired
	private DeviceCodeRepository deviceCodeRepository;
	@Autowired
	private MessageRepository messageRepository;
	@Autowired
	private UserWithdrawRepository userWithdrawRepository;
	@Autowired
	private PayLogRepository payLogRepository;
	@Autowired
	private AlbumUnlockerRepository albumUnlockerRepository;
	@Autowired
	private BroadCastRepository broadCastRepository;
	@Autowired
	private BroadCastLikerRepository broadCastLikerRepository;
	@Autowired
	private BroadCastSignerRepository broadCastSignerRepository;
	@Autowired
	private CheckWhiteListRepository checkWhiteListRepository;
	@Autowired
	private ContactWayWhiteListRepository contactWayWhiteListRepository;
	@Autowired
	private UserReportRepository userReportRepository;
	@Autowired
	private EntityManager em;
	
	@Override
	public R register(String phone, String password, int sex, String applyCodeInfo) {
		Date curDate = new Date();
		
		// 判断是否已经存在注册用户
		MUserEntity ue = mUserRepository.findOneByUsername(phone);
		if(ue != null) {
			return R.error(202, "已经存在注册用户");
		}
		
		// 添加新注册用户
		String salt = RandomStringUtils.randomAlphanumeric(20);
		
		MUserEntity user = new MUserEntity();
		user.setUsername(phone);
		user.setPassword(encrypt(password, salt));
		user.setSalt(salt); // 密钥
		user.setStatus(true);
		user.setIdentity(0);
		user.setRegisterTime(curDate);
		user.setCreateTime(curDate);
		user.setSex(sex);
		user.setApplyCodeInfo(applyCodeInfo);
		user.setPhone(phone);
		user.setCheckLimit(0);
		user.setWallet(BigDecimal.ZERO);
		user.setFrozenWallet(BigDecimal.ZERO);
		if(sex == 1) {
			// 随机生成认证码
			String identityCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
			user.setIdentityCode(identityCode);
		}
		em.persist(user);
		
		// 返回新注册用户的id，填写个人资料
		MUserEntity newUser = mUserRepository.findOneByUsername(phone);
		JSONObject jo = new JSONObject();
		jo.put("userId", newUser.getId());
		
		R r = new R();
		r.put("code", 200);
		r.put("msg", "操作成功");
		r.put("data", jo);
		return r;
	}

	@Override
	public R updateUserSex(Long userId, int sex) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		if(user == null) {
			return R.error(202, "用户不存在");
		}
		
		user.setSex(sex);
		em.merge(user);
		JSONObject jo = new JSONObject();
		jo.put("sex", sex);
		
		return R.success().put("data", jo);
	}	

	@Override
	public R forgetPassword(String phone, String newPassword) {
		MUserEntity user = mUserRepository.findOneByUsername(phone);
		if(user == null) {
			return R.error(202, "用户不存在");
		}
		
		String salt = RandomStringUtils.randomAlphanumeric(20);
		
		user.setPassword(encrypt(newPassword, salt));
		user.setSalt(salt);
		em.merge(user);

		return R.success();
	}
	
	@Override
	public R login(String username, String password, String deviceCode) {
		MUserEntity user = mUserRepository.findOneByUsername(username);
		// 账号不存在、密码错误
		if(user == null || !user.getPassword().equals(encrypt(password, user.getSalt()))) {
			return R.error(202, "账号或密码不正确");
		}
		
		// 账号被锁定
		if(user.getStatus() == false) {
			return R.error(203, "账号已被锁定，请联系客服");
		}
		
		DeviceCodeEntity deviceCodeEntity = deviceCodeRepository.findOneByUserIdAndDeviceCode(user.getId(), deviceCode);
		if(deviceCodeEntity == null) { // 第一次登录，新增用户设备码信息
			deviceCodeEntity = new DeviceCodeEntity();
			deviceCodeEntity.setUserId(user.getId());
			deviceCodeEntity.setDeviceCode(deviceCode);
			deviceCodeEntity.setStatus(true);
			deviceCodeEntity.setCreateTime(new Date());
			em.persist(deviceCodeEntity);
		} else { // 设备码存在的情况下，要判断是否被封禁
			if(!deviceCodeEntity.isStatus()) {
				return R.error(204, "设备已被封禁，请联系客服");
			}
		}
		
		user.setLoginTime(new Date());
		em.merge(user);
		
		R r = R.success("登录成功");
		r.put("data", user);
		
		return r;
	}
	
	@Override
	public R updateUserInfo(MUserEntity user) {
		MUserEntity u = mUserRepository.findOne(user.getId());
		u.setAvatar(user.getAvatar());
		u.setAvatarStatus(true);
		u.setNickname(user.getNickname());
		u.setProvince(user.getProvince());
		u.setCity(user.getCity());
		u.setAge(user.getAge());
		u.setOccupation(user.getOccupation());
		u.setHeight(user.getHeight());
		u.setWeight(user.getWeight());
		u.setBust(user.getBust());
		u.setCupSize(user.getCupSize());
		u.setStyle(user.getStyle());
		u.setLanguage(user.getLanguage());
		u.setRelationship(user.getRelationship());
		u.setWechat(user.getWechat());
		u.setQq(user.getQq());
		u.setIntroduce(user.getIntroduce());
		u.setDatingProgram(user.getDatingProgram());
		u.setDatingCodition(user.getDatingCodition());
		u.setDatingMoney(user.getDatingMoney());
		em.merge(u);
		return R.success("更新成功");
	}

	@Override
	public R bindPhone(Long userId, String phone) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		user.setId(userId);
		user.setPhone(phone);
		em.merge(user);
		return R.success("绑定成功");
	}

	@Override
	public R updatePwd(Long userId, String oldPassword, String newPassword) {
		MUserEntity user = em.find(MUserEntity.class, userId);	
		String salt = user.getSalt();
		if(!user.getPassword().equals(encrypt(oldPassword.trim(), salt))) {
			return R.error(202, "旧密码有误，请重新输入");
		}
		
		String newSalt = RandomStringUtils.randomAlphanumeric(20);
		user.setSalt(newSalt);
		user.setPassword(encrypt(newPassword.trim(), newSalt));
		em.merge(user);
		
		return R.success();
	}

	@Override
	public R getAllUserInfo(Long userId, String province, String city, int sex, int type, Integer page, Integer pageSize) {
		Pageable pageable = null;
		if(page != null && pageSize != null) {
			page = (page - 1) * pageSize;
			pageable = new PageRequest(page, pageSize);
		}
		
		List<Long> accessDefriendList = relationshipRepository.getAccessDefriendList(userId);
		List<Long> passiveDefriendList = relationshipRepository.getPassiveDefriendList(userId);
		
		// 获取当前用户的经纬度
		MUserEntity curUser = em.find(MUserEntity.class, userId);
		UserLocationEntity curUserLocation = userLocationRepository.findOneByUser(curUser);
		BigDecimal curLon = BigDecimal.ZERO;
		BigDecimal curLat = BigDecimal.ZERO;
		if(curUserLocation != null) {
			curLon = curUserLocation.getLongitude(); // 当前用户经度
			curLat = curUserLocation.getLatitude(); // 当前用户纬度
		}
		
		if(type == 1) { // 热门（根据入参sex决定是男热门列表还是女热门列表）
			StringBuilder sql = new StringBuilder();
			sql.append("select euser.id \n");
			sql.append("from e_user euser \n");
			sql.append("left join \n");
			sql.append("(select passive_id, count(passive_id) as c from e_user_follow where follow = 1 group by passive_id) t \n");
			sql.append("on euser.id = t.passive_id \n");
			sql.append("where euser.status = true and euser.check_limit != 3 and euser.sex = :sex \n");
			if(StringUtils.isNotBlank(province)) {
				sql.append("and province = :province \n");
			}
			if(StringUtils.isNotBlank(city)) {
				sql.append("and city = :city \n");
			}
			sql.append("order by t.c desc \n");
			javax.persistence.Query followQuery = em.createNativeQuery(sql.toString());
			followQuery.setParameter("sex", sex);
			if(StringUtils.isNotBlank(province)) {
				followQuery.setParameter("province", province);
			}
			if(StringUtils.isNotBlank(city)) {
				followQuery.setParameter("city", city);
			}
			if(page != null && pageSize != null) {
				followQuery.setFirstResult(page);
				followQuery.setMaxResults(pageSize);
			}
			List<BigInteger> followIds = followQuery.getResultList();
			List<MUserEntity> data = new ArrayList<>();
			for(BigInteger id : followIds) {
				MUserEntity user = em.find(MUserEntity.class, id.longValue());
				// 过滤没有填写邀请码的男用户
				if(user.getSex() == 0 && user.getIdentity() == 0) {
					continue;
				}
				data.add(user);
			}
			
			data.remove(curUser);
			
			// 去掉拉黑的用户
			for(Long defriendId : accessDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					data.remove(user);
				}
			}
			// 被别人拉黑，也不能看到该用户信息
			for(Long  defriendId : passiveDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					data.remove(user);
				}
			}
			
			// 额外的返参
			for(MUserEntity user : data) {
				UserLocationEntity userLocation = userLocationRepository.findOneByUser(user);
				double distance = 0.0;
				if(null != userLocation) {
					BigDecimal lon = userLocation.getLongitude();
					BigDecimal lat = userLocation.getLatitude();
					// 计算距离
					distance = LocationUtils.getDistance(curLon.longValue(), curLat.longValue(),
							lon.longValue(), lat.longValue());
				}
				user.setDistance(distance);
				// 是否关注该用户
				UserFollowEntity follow = relationshipRepository.findOneByActiveIdAndPassiveId(userId, user.getId());
				if(null != follow) {
					user.setIsfollow(follow.isFollow());
				}
				
				TokenEntity token = tokenRepository.findByUserId(user.getId());
				if(token != null) {
					user.setOnline(true);
				} else {
					user.setOnline(false);
				}
			}
			
			return R.success().put("data", data);
		}
		
		if(type == 2) { // 新来（最近7天注册的用户）
			Calendar calendar = Calendar.getInstance();
			calendar.add(Calendar.DATE, -7);
			Date date = calendar.getTime();
			
			StringBuilder sql = new StringBuilder();
			sql.append("from MUserEntity where sex = :sex");
			if(StringUtils.isNotBlank(province)) {
				sql.append(" and province = :province");
			}
			if(StringUtils.isNotBlank(city)) {
				sql.append(" and city = :city");
			}
			sql.append(" and registerTime >= :date");
			sql.append(" and status = :status");
			sql.append(" and checkLimit != :checkLimit");
			sql.append(" order by registerTime desc");
			javax.persistence.Query query = em.createQuery(sql.toString());
			query.setParameter("sex", sex);
			if(StringUtils.isNotBlank(province)) {
				query.setParameter("province", province);
			}
			if(StringUtils.isNotBlank(city)) {
				query.setParameter("city", city);
			}
			query.setParameter("status", true);
			query.setParameter("checkLimit", 3);
			query.setParameter("date", date);
			if(page != null && pageSize != null) {
				query.setFirstResult(page);
				query.setMaxResults(pageSize);
			}
			List<MUserEntity> allUserList = query.getResultList();
			// 去掉拉黑的用户
			for(Long defriendId : accessDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					allUserList.remove(user);
				}
			}
			// 被别人拉黑，也不能看到该用户信息
			for(Long  defriendId : passiveDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					allUserList.remove(user);
				}
			}
			// 过滤自己
			allUserList.remove(curUser);	
			
			for(MUserEntity user : allUserList) {
				UserLocationEntity userLocation = userLocationRepository.findOneByUser(user);
				double distance = 0.0;
				if(null != userLocation) {
					BigDecimal lon = userLocation.getLongitude();
					BigDecimal lat = userLocation.getLatitude();
					// 计算距离
					distance = LocationUtils.getDistance(curLon.longValue(), curLat.longValue(),
							lon.longValue(), lat.longValue());
				}
				user.setDistance(distance);
				// 是否关注该用户
				UserFollowEntity follow = relationshipRepository.findOneByActiveIdAndPassiveId(userId, user.getId());
				if(null != follow) {
					user.setIsfollow(follow.isFollow());
				}
				
				TokenEntity token = tokenRepository.findByUserId(user.getId());
				if(token != null) {
					user.setOnline(true);
				} else {
					user.setOnline(false);
				}
			}
			return R.success().put("data", allUserList);
		}
		
		if(type == 3) { // 认证（女）或会员（男）
			StringBuilder sql = new StringBuilder();
			sql.append("from MUserEntity where sex = :sex");
			if(StringUtils.isNotBlank(province)) {
				sql.append(" and province = :province");
			}
			if(StringUtils.isNotBlank(city)) {
				sql.append(" and city = :city");
			}
			sql.append(" and identity = :identity");
			sql.append(" and status = :status");
			sql.append(" and checkLimit != :checkLimit");
			javax.persistence.Query query = em.createQuery(sql.toString());
			query.setParameter("sex", sex);
			if(StringUtils.isNotBlank(province)) {
				query.setParameter("province", province);
			}
			if(StringUtils.isNotBlank(city)) {
				query.setParameter("city", city);
			}
			if(sex == 0) {
				query.setParameter("identity", 1);
			} else if(sex == 1) {
				query.setParameter("identity", 2);
			}
			query.setParameter("status", true);
			query.setParameter("checkLimit", 3);
			if(page != null && pageSize != null) {
				query.setFirstResult(page);
				query.setMaxResults(pageSize);
			}
			List<MUserEntity> allUserList = query.getResultList();
			// 去掉拉黑的用户
			for(Long defriendId : accessDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					allUserList.remove(user);
				}
			}
			// 被别人拉黑，也不能看到该用户信息
			for(Long  defriendId : passiveDefriendList) {
				MUserEntity user = em.find(MUserEntity.class, defriendId);
				if(user != null) {
					allUserList.remove(user);
				}
			}
			// 过滤自己
			allUserList.remove(curUser);
			
			for(MUserEntity user : allUserList) {
				UserLocationEntity userLocation = userLocationRepository.findOneByUser(user);
				double distance = 0.0;
				if(null != userLocation) {
					BigDecimal lon = userLocation.getLongitude();
					BigDecimal lat = userLocation.getLatitude();
					// 计算距离
					distance = LocationUtils.getDistance(curLon.longValue(), curLat.longValue(),
							lon.longValue(), lat.longValue());
				}
				user.setDistance(distance);
				// 是否关注该用户
				UserFollowEntity follow = relationshipRepository.findOneByActiveIdAndPassiveId(userId, user.getId());
				if(null != follow) {
					user.setIsfollow(follow.isFollow());
				}
				
				TokenEntity token = tokenRepository.findByUserId(user.getId());
				if(token != null) {
					user.setOnline(true);
				} else {
					user.setOnline(false);
				}
			}
			return R.success().put("data", allUserList);
		}
		return R.success();
	}

	@Override
	public R getNearbyUserInfo(Long userId, BigDecimal lon, BigDecimal lat) {
		List<Map<String, Object>> nearbyUserInfo = userLocationRepository.getNearbyUserDistance(userId, lon, lat);
		JSONArray ja = new JSONArray();
		for(int i = 0; i < nearbyUserInfo.size(); i++) {
			Map<String, Object> map = nearbyUserInfo.get(i);
			Long userIdTmp = (Long) map.get("userId");
			BigDecimal distance = (BigDecimal) map.get("distance");
			MUserEntity user = em.find(MUserEntity.class, userIdTmp);
			if(user == null) {
				continue;
			}
			JSONObject jo = JSONUtils.fromObject(user, new String[] {"inviteCode", "userPhotos", "location"});
			jo.put("distance", distance.setScale(2, BigDecimal.ROUND_HALF_UP));
			ja.add(jo);
		}
		
		return R.success().put("data", ja);
	}

	@Override
	public R searchUserInfo(final String nickname, final String age,final String height,final String weight,final String cupSize,final String occupation,final String style,
			final String language,final String relationship,final String dationProgram,final String datingCodition) {
		Specification<MUserEntity> specification = new Specification<MUserEntity>() {
			@Override
			public Predicate toPredicate(Root<MUserEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				if(StringUtils.isNotBlank(nickname)) {
					Predicate nicknamePredicate = cb.like(root.<String>get("nickname"), "%" + nickname + "%");
					predicates.add(nicknamePredicate);
				}
				if(StringUtils.isNotBlank(age)) {
					String[] ages = age.split("-");
					Predicate agePredicate = cb.between(root.<Integer>get("age"), Integer.valueOf(ages[0]), Integer.valueOf(ages[1]));
					predicates.add(agePredicate);
				}
				if(StringUtils.isNotBlank(height)) {
					String[] heights = height.split("-");
					Predicate heightPredicate = cb.between(root.<Integer>get("height"), Integer.valueOf(heights[0]), Integer.valueOf(heights[1]));
					predicates.add(heightPredicate);
				}
				if(StringUtils.isNotBlank(weight)) {
					String[] weights = weight.split("-");
					Predicate weightPredicate = cb.between(root.<Integer>get("weight"), Integer.valueOf(weights[0]), Integer.valueOf(weights[1]));
					predicates.add(weightPredicate);
				}
				if(StringUtils.isNotBlank(cupSize)) {
					Predicate cupSizePredicate = cb.equal(root.<String>get("cupSize"), cupSize);
					predicates.add(cupSizePredicate);
				}
				if(StringUtils.isNotBlank(occupation)) {
					Predicate occupationPredicate = cb.equal(root.<String>get("occupation"), occupation);
					predicates.add(occupationPredicate);
				}
				if(StringUtils.isNotBlank(style)) {
					Predicate stylePredicate = cb.equal(root.<String>get("style"), style);
					predicates.add(stylePredicate);
				}
				if(StringUtils.isNotBlank(language)) {
					Predicate languagePredicate = cb.equal(root.<String>get("language"), language);
					predicates.add(languagePredicate);
				}
				if(StringUtils.isNotBlank(relationship)) {
					Predicate relationshipPredicate = cb.equal(root.<String>get("relationship"), relationship);
					predicates.add(relationshipPredicate);
				}
				if(StringUtils.isNotBlank(dationProgram)) {
					Predicate dpPredicate = cb.like(root.<String>get("dationProgram"), "%" + dationProgram + "%");
					predicates.add(dpPredicate);
				}
				if(StringUtils.isNotBlank(datingCodition)) {
					Predicate dcPredicate = cb.like(root.<String>get("dationCodition"), "%" + datingCodition + "%");
					predicates.add(dcPredicate);
				}
				Predicate sexPredicate = cb.equal(root.<Integer>get("sex"), 1);
				predicates.add(sexPredicate);
				
				Predicate statusPredicate = cb.equal(root.<Boolean>get("status"), true);
				predicates.add(statusPredicate);
				
				Predicate checkLimitPredicate = cb.notEqual(root.<Integer>get("checkLimit"), 3);
				predicates.add(checkLimitPredicate);
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
		List<MUserEntity> list = mUserRepository.findAll(specification);
		
		return R.success().put("data", list);
	}
	
	@Override
	public R getUserInfo(Long userId, Long viewerId) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		List<UserPhotoEntity> list = user.getUserPhotos();
		if(CollectionUtils.isNotEmpty(list)){
			for(UserPhotoEntity userPhotoEntity : list){
				if(userPhotoEntity.getLevel() == 1){	//阅后即焚图片状态默认为true可看
					userPhotoEntity.setCheckStatus(true);
				}else if(userPhotoEntity.getLevel() == 2){	//红包图片状态默认为false不可看
					userPhotoEntity.setCheckStatus(false);
				}
				
				PhotoViewerEntity photoViewerEntity = photoViewerRepository.findTopByUserIdAndPhotoIdAndViewerId(userId, userPhotoEntity.getId(), viewerId);
				if(photoViewerEntity != null) {
					userPhotoEntity.setCheckStatus(!userPhotoEntity.getCheckStatus());
				}
			}
		}
		MemberEntity member = memberRepository.findByUserId(user.getId());
		if(member != null) {
			if(member.getSurplusDays() > 0) {
				user.setMemberSurplusDays(String.format("%d天", member.getSurplusDays()));
			} else if(member.getSurplusDays() < 1 && member.getSurplusDays() > 0) {
				user.setMemberSurplusDays("不足一天");
			} else {
				user.setMemberSurplusDays("0天");
			}
		}
		R r = R.success().put("data", user);
		return r;
	}
	

	@Override
	public R updateUserLocation(Long userId, double lon, double lat) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		if(user == null) {
			return R.error(202, "不存在的用户");
		}
		
		UserLocationEntity le = userLocationRepository.findOneByUser(user);
		if(le == null) {
			le = new UserLocationEntity();
			le.setLongitude(BigDecimal.valueOf(lon).setScale(6, BigDecimal.ROUND_HALF_UP));
			le.setLatitude(BigDecimal.valueOf(lat).setScale(6, BigDecimal.ROUND_HALF_UP));
			le.setCreateTime(new Date());
			le.setUser(user);
			em.persist(le);
		} else {
			le.setLongitude(BigDecimal.valueOf(lon).setScale(6, BigDecimal.ROUND_HALF_UP));
			le.setLatitude(BigDecimal.valueOf(lat).setScale(6, BigDecimal.ROUND_HALF_UP));
			le.setUpdateTime(new Date());
			em.merge(le);
		}
		
		return R.success();
	}

	/**
	 * 加密处理
	 * 
	 * @param password
	 * @return
	 */
	private String encrypt(String password, String salt) {
		//sha256加密
		String str = new Sha256Hash(password, salt).toHex();
		return str;
	}
	
	@Override
	public R updateCheckLimit(Long userId, Integer checkLimit) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		user.setCheckLimit(checkLimit);
		em.merge(user);
		return R.success();
	}

	/**
	 * 设置付费相册金额
	 * 
	 * @param userId	用户ID
	 * @param albumAmount	付费相册设置金额
	 * @return
	 */
	public R updateAlbumAmount(Long userId, BigDecimal albumAmount){
		MUserEntity user = em.find(MUserEntity.class, userId);
		user.setAlbumAmount(albumAmount);
		em.merge(user);
		return R.success();
	}
	
	/**
	 * 更新钱包金额
	 * 
	 * @param userId	用户ID
	 * @param amount	增加金额
	 * @return
	 */
	public R updateWallet(Long userId, BigDecimal amount){
		synchronized (MUserController.class) {
			MUserEntity user = em.find(MUserEntity.class, userId);
			if(user == null){
				return R.error(202, "该用户不存在");
			}
			BigDecimal wallet = user.getWallet();
			if(wallet == null){
				wallet = BigDecimal.ZERO;
			}
			user.setWallet(wallet.add(amount));
			em.merge(user);
			return R.success();
		}
	}

	@Override
	public R uploadAvatar(Long userId, String imagePath) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		user.setAvatar(imagePath);
		em.merge(user);
		return R.success().put("data", imagePath);
	}
	
	@Override
	public R identity(Long userId, String identityPhoto) {
		MUserEntity user = em.find(MUserEntity.class, userId);
		if(user != null) {
			user.setIdentityPhoto(identityPhoto);
			em.merge(user);
		}
		
		return R.success();
	}
	
	
	@Override
	public PageUtils queryPage(final Query query) {
		// 规格定义
		Specification<MUserEntity> specification = new Specification<MUserEntity>() {
			@Override
			public Predicate toPredicate(Root<MUserEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				if(StringUtils.isNotBlank((String) query.get("phone"))) {
					Predicate likePhone = cb.like(root.get("phone").as(String.class), "%" + query.get("phone") + "%");
					predicates.add(likePhone);
				}
				
				if(StringUtils.isNotBlank((String) query.get("nickname"))) {
					Predicate likePhone = cb.like(root.get("nickname").as(String.class), "%" + query.get("nickname") + "%");
					predicates.add(likePhone);
				}
				
				List<Predicate> orPredicates = new ArrayList<>();
				if(StringUtils.isNotBlank((String) query.get("area"))) {
					Predicate provinceLike = cb.like(root.<String>get("province"), "%" + query.get("area") + "%");
					
					Predicate cityLike = cb.like(root.<String>get("city"), "%" + query.get("city") + "%");
					
					orPredicates.add(provinceLike);
					orPredicates.add(cityLike);
					Predicate areaPredicate = cb.or(orPredicates.toArray(new Predicate[0]));
					predicates.add(areaPredicate);
				}
				
				Predicate sexPredicate = cb.equal(root.get("sex").as(Integer.class), query.get("sex"));
				predicates.add(sexPredicate);
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
		List<Order> orders = new ArrayList<>();
		orders.add(new Order(Direction.DESC, "registerTime"));
		Pageable pageable = new PageRequest(query.getPage() - 1, query.getLimit(), new Sort(orders)); // 页头从0开始
		Page<MUserEntity> page = this.mUserRepository.findAll(specification, pageable);
		
		List<Map<Object, String>> list = new ArrayList<>();
		for(MUserEntity user : page) {
			Map<Object, String> map = new HashMap<>();
			map.put("id", user.getId().toString());
			map.put("username", user.getUsername());
			map.put("area", String.format("%s%s", user.getProvince(), user.getCity()));
			map.put("nickname", user.getNickname());
			map.put("phone", user.getPhone());
			if(user.getSex() == 0) {	
				if(user.getIdentity() == 3 || user.getIdentity() == 1) {
					map.put("status", "已激活");
				} else {
					map.put("status", "未激活");
				}
			} else {
				map.put("status", "已激活");
			}
			
			if(user.getSex() == 0) {
				if(user.getIdentity() == 1) {
					map.put("identity", "会员");
				} else {
					map.put("identity", "非会员");
				}
			} else {
				if(user.getIdentity() == 2) {
					map.put("identity", "真实");
				} else {
					map.put("identity", "未认证");
				}
			}
			map.put("applyCodeInfo", user.getApplyCodeInfo());
			map.put("loginTime", user.getLoginTime() == null ? "" : user.getLoginTime().toString());
			map.put("registerTime", user.getRegisterTime() == null ? "" : user.getRegisterTime().toString());
			map.put("statusTmp", Boolean.toString(user.getStatus()));
			map.put("statusTxt", user.getStatus() ? "解冻" : "冻结");
			map.put("btnTxt", user.getStatus() ? "冻结" : "解冻");
			list.add(map);
		}
		
		PageUtils pageUtil = new PageUtils(list, Long.valueOf(page.getTotalElements()).intValue(), query.getLimit(), query.getPage());
		return pageUtil;
	}

	@Override
	public PageUtils queryDeviceCodePage(final Query query) {
		StringBuilder sql = new StringBuilder();
		sql.append("select dc.id \n");
		sql.append("      ,user.province \n");
		sql.append("      ,user.city \n");
		sql.append("      ,user.username \n");
		sql.append("      ,user.nickname \n");
		sql.append("      ,user.phone \n");
		sql.append("      ,dc.device_code \n");
		sql.append("      ,dc.create_time \n");
		sql.append("      ,dc.status \n");
		sql.append("from e_device_code dc \n");
		sql.append("join e_user user on dc.user_id = user.id \n");
		sql.append("where 1=1 \n");
		if(StringUtils.isNotBlank((String) query.get("area"))) {
			sql.append("and user.province like concat('%', concat(:area, '%')) \n");
			sql.append("or user.city like concat('%', concat(:area, '%')) \n");
		}
		if(StringUtils.isNotBlank((String) query.get("nickname"))) {
			sql.append("and user.nickname like concat('%', concat(:nickname, '%')) \n");
		}
		if(StringUtils.isNotBlank((String) query.get("phone"))) {
			sql.append("and user.phone like concat('%', concat(:phone, '%')) \n");
		}
		sql.append("order by dc.create_time desc \n");
		javax.persistence.Query allQy = em.createNativeQuery(sql.toString());
		if(StringUtils.isNotBlank((String) query.get("area"))) {
			allQy.setParameter("area", query.get("area"));
		}
		if(StringUtils.isNotBlank((String) query.get("nickname"))) {
			allQy.setParameter("nickname", query.get("nickname"));
		}
		if(StringUtils.isNotBlank((String) query.get("phone"))) {
			allQy.setParameter("phone", query.get("phone"));
		}
		List allResults = allQy.getResultList();
		
		sql.append("limit :page, :size \n");
		
		javax.persistence.Query qy = em.createNativeQuery(sql.toString());
		if(StringUtils.isNotBlank((String) query.get("area"))) {
			qy.setParameter("area", query.get("area"));
		}
		if(StringUtils.isNotBlank((String) query.get("nickname"))) {
			qy.setParameter("nickname", query.get("nickname"));
		}
		if(StringUtils.isNotBlank((String) query.get("phone"))) {
			qy.setParameter("phone", query.get("phone"));
		}
		qy.setParameter("page", query.get("offset"));
		qy.setParameter("size", query.get("limit"));
		List resultList = qy.getResultList();
		
		List<Map<String, Object>> list = new ArrayList<>();
		for(Object row : resultList) {
			Object[] cells = (Object[]) row;
			Map<String, Object> map = new HashMap<>();
			map.put("id", cells[0]);
			map.put("area", String.format("%s%s", cells[1], cells[2]));
			map.put("username", cells[3]);
			map.put("nickname", cells[4]);
			map.put("phone", cells[5]);
			map.put("deviceCode", cells[6]);
			map.put("createTime", cells[7]);
			map.put("status", Boolean.valueOf(cells[8].toString()) ? "未封禁" : "已封禁");
			list.add(map);
		}
		PageUtils pageUtil = new PageUtils(list, allResults.size(), query.getLimit(), query.getPage());
		
		return pageUtil;
	}

	@Override
	public R editDeviceCode(Long id, boolean status) {
		DeviceCodeEntity deviceCode = em.find(DeviceCodeEntity.class, id);
		// 封禁所有相同的设备码
		List<DeviceCodeEntity> deviceCodes = deviceCodeRepository.findByDeviceCode(deviceCode.getDeviceCode());
		for(DeviceCodeEntity code : deviceCodes) {
			code.setStatus(status);
			em.merge(code);
			
			TokenEntity token = tokenRepository.findByUserId(code.getUserId());
			if(token != null) {
				em.remove(token);
			}
		}
		
		return R.success();
	}

	@Override
	public PageUtils queryIdentityPage(final Query query) {
		Specification<MUserEntity> specification = new Specification<MUserEntity>() {
			@Override
			public Predicate toPredicate(Root<MUserEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				
				List<Predicate> orPredicates = new ArrayList<>();
				if(StringUtils.isNotBlank((String) query.get("area"))) {
					Predicate provinceLike = cb.like(root.<String>get("province"), "%" + query.get("area") + "%");
					
					Predicate cityLike = cb.like(root.<String>get("city"), "%" + query.get("city") + "%");
					
					orPredicates.add(provinceLike);
					orPredicates.add(cityLike);
					Predicate areaPredicate = cb.or(orPredicates.toArray(new Predicate[0]));
					predicates.add(areaPredicate);
				}
				
				if(StringUtils.isNotBlank((String) query.get("nickname"))) {
					Predicate nicknameLike = cb.like(root.<String>get("nickname"), "%" + query.get("nickname") + "%");
					predicates.add(nicknameLike);
				}
				
				if(StringUtils.isNotBlank((String) query.get("phone"))) {
					Predicate phoneLike = cb.like(root.<String>get("phone"), "%" + query.get("phone") + "%");
					predicates.add(phoneLike);
				}
				
				Predicate sexPredicate = cb.equal(root.<Integer>get("sex"), new Integer(1));
				predicates.add(sexPredicate);
				
				// 过滤已经通过认证的
				Predicate identityPredicate = cb.notEqual(root.<Integer>get("identity"), new Integer(2));
				predicates.add(identityPredicate);

				Predicate identityPhotoPredicate = cb.isNotNull(root.<String>get("identityPhoto"));
				predicates.add(identityPhotoPredicate);

				return cb.and(predicates.toArray(new Predicate[0]));
				
			}
		};
		Pageable pageable = new PageRequest(query.getPage() - 1, query.getLimit(),  new Sort(new Order(Direction.DESC, "updateTime")));
		Page<MUserEntity> page = mUserRepository.findAll(specification, pageable);
		int totalCount = Long.valueOf(page.getTotalElements()).intValue();
		// 解析用户信息
		List<Map<String, Object>> objList = new ArrayList<>();
		for(int i = 0; i < page.getContent().size(); i++) {
			Map<String, Object> map = new HashMap<>();
			MUserEntity user = page.getContent().get(i);
			map.put("id", user.getId());
			map.put("username", user.getUsername());
			map.put("area", String.format("%s%s", user.getProvince(), user.getCity()));
			map.put("phone", user.getPhone());
			map.put("datingArea", user.getCity());
			map.put("nickname", user.getNickname());
			map.put("identity", user.getIdentity() == 2 ? "已认证" : "未认证");
			map.put("wallet", user.getWallet());
			map.put("loginTime", user.getLoginTime());
			map.put("registerTime", user.getRegisterTime());
			map.put("identityPhoto", user.getIdentityPhoto());
			map.put("identityCode", user.getIdentityCode());
			objList.add(map);
		}
		PageUtils pageUtil = new PageUtils(objList, totalCount, query.getLimit(), query.getPage());
		return pageUtil;
	}

	@Override
	public R editIdentity(Long id, int identity) {
		MUserEntity user = em.find(MUserEntity.class, id);
		if(user != null) {
			user.setIdentity(identity);
		}
		return R.success();
	}

	@Override
	public R userDetail(Long id) {
		MUserEntity user = em.find(MUserEntity.class, id);
		Map<String, Object> map = new HashMap<>();
		if(user != null) {
			map.put("user", user);
			
			List<UserPhotoEntity> photos = user.getUserPhotos();
			map.put("photos", photos);
//			List<String> imgPath = new ArrayList<>();
//			List<Long> photoIds = new ArrayList<>();
//			List<Boolean> photoStatus = new ArrayList<>();
//			for(UserPhotoEntity photo : photos) {
//				imgPath.add(photo.getImagePath());
//				photoIds.add(photo.getId());
//				photoStatus.add(photo.isStatus());
//			}
//			map.put("photos", imgPath);
//			map.put("photoIds", photoIds);
//			map.put("photoStatus", photoStatus);
			if(user.getSex() == 1) {
				StringBuilder sql = new StringBuilder();
				sql.append("select pl.amount \n");
				sql.append("from pay_log pl \n");
				sql.append("where pl.collecter_id = :userId \n");
				sql.append("and pl.status = 1 \n");
				
				javax.persistence.Query query = em.createNativeQuery(sql.toString());
				query.setParameter("userId", user.getId());
				
				List resultList = query.getResultList();
				BigDecimal totalAmount = BigDecimal.ZERO;
				for(Object row : resultList) {
					BigDecimal amount = (BigDecimal) row;
					totalAmount = totalAmount.add(amount);
				}
				map.put("income", totalAmount);
			}
		}
		return R.success().put("data", map);
	}

	@Override
	public R userDel(Long id) {
		MUserEntity user = em.find(MUserEntity.class, id);
		if(user == null) {
			return R.error("该用户已被删除");
		}
		
		// 删除邀请码
		List<InviteCodeEntity> inviteCodes = user.getInviteCodes();
		for(InviteCodeEntity code : inviteCodes) {
			em.remove(code);
		}
		
		// 删除用户图库
		List<UserPhotoEntity> photos = user.getUserPhotos();
		for(UserPhotoEntity photo : photos) {
			em.remove(photo);
		}
		
		// 删除用户位置
		UserLocationEntity location = user.getLocation();
		if(location != null) {
			em.remove(location);
		}
		
		// 删除机器码
		List<DeviceCodeEntity> deviceCodes = deviceCodeRepository.findByUserId(user.getId());
		for(DeviceCodeEntity code : deviceCodes) {
			em.remove(code);
		}
		
		// 删除用户会员充值信息
		MemberEntity member = memberRepository.findByUserId(user.getId());
		if(member != null) {
			em.remove(member);
		}
		
		// 删除用户消息
		List<MessageEntity> messages = messageRepository.findByUserId(user.getId());
		for(MessageEntity message : messages) {
			em.remove(message);
		}
		
		// 删除用户token值
		TokenEntity token = tokenRepository.findByUserId(user.getId());
		if(token != null) {
			em.remove(token);
		}
		
		// 删除用户访问列表
		List<BigInteger> accessIds = relationshipRepository.getAccessList(user.getId());
		for(BigInteger accessId : accessIds) {
			if(accessId == null) {
				continue;
			}
			UserAccessEntity access = em.find(UserAccessEntity.class, accessId.longValue());
			if(access != null) {
				em.remove(access);
			}
		}
		
		// 删除用户拉黑列表
		List<BigInteger> defriendIds = relationshipRepository.getDefriendList(user.getId());
		for(BigInteger defriendId : defriendIds) {
			if(defriendId == null) {
				continue;
			}
			UserDefriendEntity defriend = em.find(UserDefriendEntity.class, defriendId.longValue());
			if(defriend != null) {
				em.remove(defriend);
			}
		}
		
		// 删除用户评价列表
		List<UserEvaluateEntity> evaluates = relationshipRepository.findEvaluateByPassivaId(user.getId());
		for(UserEvaluateEntity evaluate : evaluates) {
			em.remove(evaluate);
		}
		
		// 删除用户关注列表
		List<BigInteger> followIds = relationshipRepository.getAccessList(user.getId());
		for(BigInteger followId : followIds) {
			if(followId == null) {
				continue;
			}
			UserFollowEntity follow = em.find(UserFollowEntity.class, followId.longValue());
			if(follow != null) {
				em.remove(follow);
			}
		}
		
		// 删除用户提现列表
		List<UserWithdrawEntity> withdraws = userWithdrawRepository.findByUserId(user.getId());
		for(UserWithdrawEntity withdraw : withdraws) {
			em.remove(withdraw);
		}
		
		// 删除用户历史消费记录
//		List<PayLog> payLogs = payLogRepository.findByPayerId(user.getId());
//		for(PayLog payLog : payLogs) {
//			em.remove(payLog);
//		}
		
		// 删除付费相册解锁关系
		albumUnlockerRepository.deleteByUserIdOrUnlockerId(user.getId(), user.getId());
		//删除用户广播
		broadCastRepository.deleteByUserId(user.getId());
		BroadCastEntity broadCastEntity = broadCastRepository.findTopByUserId(user.getId());
		//删除广播点赞关系
		broadCastLikerRepository.deleteByLikerId(user.getId());
		if(broadCastEntity != null){
			broadCastLikerRepository.deleteByBroadCastId(broadCastEntity.getId());
		}
		//删除广播报名关系
		broadCastSignerRepository.deleteBySignerId(user.getId());
		if(broadCastEntity != null){
			broadCastSignerRepository.deleteBybroadCastId(broadCastEntity.getId());
		}
		//删除个人资料查看权限关系
		checkWhiteListRepository.deleteByUserIdOrCheckerId(user.getId(), user.getId());
		//删除联系方式查看权限关系
		contactWayWhiteListRepository.deleteByUserIdOrCheckerId(user.getId(), user.getId());
		//删除用户图片查看关系
		photoViewerRepository.deleteByUserIdOrViewerId(user.getId(), user.getId());
		//删除用户举报关系
		userReportRepository.deleteByActiveIdOrPassiveId(user.getId(), user.getId());
		
		em.remove(user);
		return R.success("删除成功");
		
	}

	@Override
	public R userFreezeOrThaw(Map<String, Object> params) {
		if(params == null || params.isEmpty()) {
			return R.error("入参为空");
		}
		String userId = (String) params.get("id");
		String status = (String) params.get("status");
		MUserEntity user = em.find(MUserEntity.class, Long.valueOf(userId));
		user.setStatus(Boolean.valueOf(status));
		em.merge(user);
		
		TokenEntity token = tokenRepository.findByUserId(Long.valueOf(userId));
		if(token != null) {
			em.remove(token);
		}
		
		return R.success("操作成功");
	}

	@Override
	public R userAvatarFreeze(Long id) {
		MUserEntity user = em.find(MUserEntity.class, id);
		if(user != null) {
			user.setAvatar("http://39.108.51.202:8080/yueye/avatarFreezeImage/avatarFreezeImage.png");
			em.merge(user);
		}
		return R.success("操作成功");
	}

}
